package com.tianji.learning.service.impl;

import com.tianji.api.client.user.UserClient;
import com.tianji.api.dto.user.UserDTO;
import com.tianji.common.utils.CollUtils;
import com.tianji.common.utils.DateUtils;
import com.tianji.common.utils.UserContext;
import com.tianji.learning.constants.RedisConstants;
import com.tianji.learning.domain.po.PointsBoard;
import com.tianji.learning.domain.vo.PointsBoardItemVO;
import com.tianji.learning.domain.vo.PointsBoardVO;
import com.tianji.learning.mapper.PointsBoardMapper;
import com.tianji.learning.query.PointsBoardQuery;
import com.tianji.learning.service.IPointsBoardService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.BoundZSetOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 学霸天梯榜 服务实现类
 * </p>
 *
 * @author Aimer
 * @since 2025-11-16
 */
@Service
@RequiredArgsConstructor
public class PointsBoardServiceImpl extends ServiceImpl<PointsBoardMapper, PointsBoard> implements IPointsBoardService {

    private final StringRedisTemplate stringRedisTemplate;
    private final UserClient userClient;
    @Override
    public PointsBoardVO queryPointsBoardBySeason(PointsBoardQuery pointsBoardQuery) {
        // 1.获取redis中的key
        LocalDateTime now = LocalDateTime.now();
        String key = RedisConstants.POINTS_BOARD_KEY_PREFIX + now.format(DateUtils.POINTS_BOARD_SUFFIX_FORMATTER);
        // 2.查询我的积分和排名（判断查当前榜单还是历史榜单）
        PointsBoard myPointBoard = pointsBoardQuery.getSeason() == null || pointsBoardQuery.getSeason() == 0? queryCurrentBoard(key):queryHistoryBoard(pointsBoardQuery.getSeason());
        // 3.查询排名列表(判断是当前榜单还是历史榜单)
        List<PointsBoard> pointsBoardList = pointsBoardQuery.getSeason() == null || pointsBoardQuery.getSeason() == 0? queryCurrentBoardList(key,pointsBoardQuery.getPageNo(),pointsBoardQuery.getPageSize()):queryHistoryBoardList(pointsBoardQuery);
        PointsBoardVO pointsBoardVO = new PointsBoardVO();
        if (myPointBoard != null){
            pointsBoardVO.setRank(myPointBoard.getRank());
            pointsBoardVO.setPoints(myPointBoard.getPoints());
        }
        if (CollUtils.isEmpty(pointsBoardList)){
            return pointsBoardVO;
        }
        // 4.获取用户信息
        Set<Long> userIds = pointsBoardList.stream().map(PointsBoard::getUserId).collect(Collectors.toSet());
        List<UserDTO> userDTOS = userClient.queryUserByIds(userIds);
        Map<Long,String> userMap = new HashMap<>(userIds.size());
        if (CollUtils.isNotEmpty(userDTOS)){
            userMap = userDTOS.stream().collect(Collectors.toMap(UserDTO::getId,UserDTO::getName));
        }
        // 5.封装数据
        List<PointsBoardItemVO> pointsBoardItemVOList = new ArrayList<>(pointsBoardList.size());
        for (PointsBoard pointsBoard : pointsBoardList) {
            PointsBoardItemVO  vo = new PointsBoardItemVO ();
            vo.setPoints(pointsBoard.getPoints());
            vo.setRank(pointsBoard.getRank());
            vo.setName(userMap.get(pointsBoard.getUserId()));
            pointsBoardItemVOList.add(vo);
        }
        pointsBoardVO.setBoardList(pointsBoardItemVOList);
        return pointsBoardVO;
    }

    private List<PointsBoard> queryHistoryBoardList(PointsBoardQuery pointsBoardQuery) {
        return null;
    }

    private List<PointsBoard> queryCurrentBoardList(String key, Integer pageNo, Integer pageSize) {
        // 1.计算分页
        int from = (pageNo - 1) * pageSize;
        // 2.查询
        Set<ZSetOperations.TypedTuple<String>> tuples = stringRedisTemplate.opsForZSet().reverseRangeByScoreWithScores(key, from, from + pageSize - 1);
        if (CollUtils.isEmpty(tuples)){
           return CollUtils.emptyList();
        }
        // 封装数据
        int rank = from + 1;
        List<PointsBoard> list = new ArrayList<>(tuples.size());
        for (ZSetOperations.TypedTuple<String> tuple : tuples) {
            String userId = tuple.getValue();
            Double points = tuple.getScore();
            if (userId == null || points == null){
                continue;
            }
            PointsBoard pointsBoard = new PointsBoard();
            pointsBoard.setUserId(Long.valueOf(userId));
            pointsBoard.setPoints(points.intValue());
            pointsBoard.setRank(rank++);
            list.add(pointsBoard);
        }
        return list;
    }

    private PointsBoard queryHistoryBoard(Long season) {
        return null;
    }

    private PointsBoard queryCurrentBoard(String key) {
        // 1.绑定key
        BoundZSetOperations<String, String> ops = stringRedisTemplate.boundZSetOps(key);
        // 2.获取当前登录用户信息
        Long userId = UserContext.getUser();
        // 3.查询积分
        Double score = ops.score(userId.toString());
        // 4.查询排名
        Long rank = ops.reverseRank(userId.toString());
        // 5.封装数据
        PointsBoard pointsBoard = new PointsBoard();
        pointsBoard.setUserId(userId);
        pointsBoard.setPoints(score == null? 0:score.intValue());
        pointsBoard.setRank(rank == null? 0:rank.intValue() + 1);
        return pointsBoard;
    }


}
